# -*- coding: utf-8 -*-
"""
HaaS506 RTU GPIO模块
简化版本 - GPIO控制和状态读取
"""

from driver import GPIO
import utime

# GPIO引脚定义
_state_led = None
_net_led = None
_di1 = None
_di2 = None
_relay1 = None
_relay2 = None

# LED状态
_state_led_mode = "off"
_net_led_mode = "off"
_led_thread_running = False

# 报警状态
_alarm_state = {
    "power_failure": False,  # 断电报警状态
    "relay1_flash_state": False,  # relay1闪烁状态
    "last_flash_time": 0,  # 上次闪烁时间
    "last_interrupt_time": 0,  # 上次中断时间(防抖动)
    "last_di1_state": -1,  # 上次DI1状态
}

# 用于线程安全的锁
_alarm_lock = False

# 防抖动时间(毫秒)
_DEBOUNCE_TIME_MS = 100


def _di1_irq_handler(data):
    """DI1中断回调函数 - 断电检测"""
    global _alarm_state, _alarm_lock

    # 防抖动检查
    current_time_ms = utime.ticks_ms()
    last_interrupt_time = _alarm_state.get("last_interrupt_time", 0)

    if utime.ticks_diff(current_time_ms, last_interrupt_time) < _DEBOUNCE_TIME_MS:
        return  # 忽略抖动

    # 使用简单的锁机制防止竞态条件
    if _alarm_lock:
        return

    _alarm_lock = True

    try:
        # 读取当前DI1状态
        if _di1:
            di1_state = _di1.read()

            # 更新中断时间
            _alarm_state["last_interrupt_time"] = current_time_ms

            # 检查状态是否真的改变了
            if di1_state == _alarm_state.get("last_di1_state", -1):
                return  # 状态未改变，忽略

            _alarm_state["last_di1_state"] = di1_state

            # 立即打印日志（添加flush确保输出）
            print("[GPIO] DI1 interrupt triggered, state: {}".format(di1_state))

            # 创建状态副本进行原子更新
            current_power_failure = _alarm_state["power_failure"]

            # DI1=0表示断电(pullup时，断开为低电平)
            if di1_state == 0 and not current_power_failure:
                # 断电开始 - 立即上传数据
                print("[GPIO] Power failure detected! Starting alarm...")

                # 设置断电状态
                _alarm_state["power_failure"] = True
                _alarm_state["last_flash_time"] = utime.time()

                # 立即尝试采集和上传数据
                print("[GPIO] Collecting emergency data...")

                try:
                    import rtu_data

                    # 紧急采集，不对齐时间
                    data = rtu_data.collect_data(emergency=True)
                    if data:
                        print("[GPIO] Emergency data collected successfully")

                except Exception as e:
                    print("[GPIO] Failed to collect emergency data: {}".format(e))

            elif di1_state == 1 and current_power_failure:
                # 断电恢复
                print("[GPIO] Power restored, stopping alarm...")

                _alarm_state["power_failure"] = False
                _alarm_state["relay1_flash_state"] = False
                # 恢复relay1为系统运行指示
                if _relay1:
                    _relay1.write(1)
                print("[GPIO] Alarm stopped")

    except Exception as e:
        print("[GPIO] DI1 IRQ handler error: {}".format(e))

    finally:
        _alarm_lock = False


def init():
    """初始化GPIO模块"""
    global _state_led, _net_led, _di1, _di2, _relay1, _relay2

    try:
        # 初始化LED
        _state_led = GPIO()
        _state_led.open("STATE_LED")
        _net_led = GPIO()
        _net_led.open("NET_LED")

        # 初始化DI1作为中断输入(断电检测)
        _di1 = GPIO()
        _di1.open("DI1")
        _di1.on(_di1_irq_handler)  # 设置中断回调

        # 初始化DI2作为普通输入
        _di2 = GPIO()
        _di2.open("DI2")

        # 初始化继电器
        _relay1 = GPIO()
        _relay1.open("RELAY1")
        _relay2 = GPIO()
        _relay2.open("RELAY2")

        # 初始状态
        _state_led.write(0)
        _net_led.write(0)
        _relay1.write(0)
        _relay2.write(0)

        print("[GPIO] GPIO module initialized with DI1 interrupt")
        return True

    except Exception as e:
        print("[GPIO] Init error: {}".format(e))
        return False


def set_state_led_mode(mode):
    """设置系统状态LED模式"""
    global _state_led_mode
    _state_led_mode = mode
    # print("[GPIO] State LED mode: {}".format(mode))


def set_net_led_mode(mode):
    """设置网络状态LED模式"""
    global _net_led_mode
    _net_led_mode = mode
    # print("[GPIO] Network LED mode: {}".format(mode))


def update_leds():
    """更新LED状态"""
    if not _state_led or not _net_led:
        return

    try:
        # 更新状态LED
        if _state_led_mode == "on":
            _state_led.write(1)
        elif _state_led_mode == "off":
            _state_led.write(0)
        elif _state_led_mode == "fast_blink":
            _state_led.write(1)
            utime.sleep_ms(100)
            _state_led.write(0)
        elif _state_led_mode == "slow_blink":
            _state_led.write(1)
            utime.sleep_ms(200)
            _state_led.write(0)

        # 更新网络LED
        if _net_led_mode == "on":
            _net_led.write(1)
        elif _net_led_mode == "off":
            _net_led.write(0)
        elif _net_led_mode == "fast_blink":
            _net_led.write(1)
            utime.sleep_ms(100)
            _net_led.write(0)
        elif _net_led_mode == "slow_blink":
            _net_led.write(1)
            utime.sleep_ms(200)
            _net_led.write(0)

    except Exception as e:
        print("[GPIO] LED update error: {}".format(e))


def read_digital_inputs():
    """读取数字输入状态"""
    if not _di1 or not _di2:
        return None

    try:
        return {"di1": _di1.read(), "di2": _di2.read()}
    except Exception as e:
        print("[GPIO] Read DI error: {}".format(e))
        return None


def set_relay(relay_id, state):
    """设置继电器状态"""
    try:
        if relay_id == 1 and _relay1:
            _relay1.write(1 if state else 0)
            print("[GPIO] Relay1 set to {}".format(state))
            return True
        elif relay_id == 2 and _relay2:
            _relay2.write(1 if state else 0)
            print("[GPIO] Relay2 set to {}".format(state))
            return True
        else:
            print("[GPIO] Invalid relay ID: {}".format(relay_id))
            return False

    except Exception as e:
        print("[GPIO] Relay control error: {}".format(e))
        return False


def get_relay_state(relay_id):
    """获取继电器状态"""
    try:
        if relay_id == 1 and _relay1:
            return bool(_relay1.read())
        elif relay_id == 2 and _relay2:
            return bool(_relay2.read())
        else:
            return False
    except Exception as e:
        print("[GPIO] Get relay state error: {}".format(e))
        return False


def get_all_gpio_status():
    """获取所有GPIO状态"""
    try:
        di_status = read_digital_inputs()
        return {
            "digital_inputs": di_status,
            "relay1": get_relay_state(1),
            "relay2": get_relay_state(2),
            "state_led_mode": _state_led_mode,
            "net_led_mode": _net_led_mode,
        }
    except Exception as e:
        print("[GPIO] Get status error: {}".format(e))
        return None


def indicate_system_running():
    """点亮relay1作为系统运行指示灯"""
    try:
        if _relay1:
            _relay1.write(1)
            print("[GPIO] System running indicator ON (Relay1)")
            return True
        else:
            print("[GPIO] Relay1 not initialized")
            return False
    except Exception as e:
        print("[GPIO] System running indicator error: {}".format(e))
        return False


def flash_startup_indicator():
    """启动时点亮relay1指示灯"""
    try:
        if _relay1:
            # 直接点亮，不闪烁
            _relay1.write(1)
            print("[GPIO] System running indicator turned ON")
            return True
        else:
            print("[GPIO] Relay1 not initialized")
            return False
    except Exception as e:
        print("[GPIO] Startup indicator error: {}".format(e))
        return False


def get_power_status():
    """获取当前电源状态"""
    global _alarm_state, _alarm_lock

    if not _di1:
        return {"status": "unknown", "di1_state": -1}

    # 等待锁释放
    retry_count = 0
    while _alarm_lock and retry_count < 10:
        utime.sleep_ms(10)
        retry_count += 1

    try:
        # 读取DI1状态，0=断电(pullup配置下)
        di1_state = _di1.read()

        # 创建状态副本避免竞态条件
        power_failure = _alarm_state["power_failure"]

        return {
            "status": "failure" if power_failure else "normal",
            "di1_state": di1_state,
            "alarm_active": power_failure,
        }

    except Exception as e:
        print("[GPIO] Get power status error: {}".format(e))
        return {"status": "error", "error": str(e)}


def update_power_alarm():
    """更新断电报警状态(在主循环中调用)"""
    global _alarm_state

    if not _di1 or not _relay1:
        return

    try:
        # 检查电源恢复（因为只有falling中断，需要手动检查恢复）
        if _alarm_state["power_failure"]:
            di1_state = _di1.read()
            if di1_state == 1:  # 电源恢复
                print("[GPIO] Power restored (detected in update), stopping alarm...")

                _alarm_state["power_failure"] = False
                _alarm_state["relay1_flash_state"] = False
                # 恢复relay1为系统运行指示
                _relay1.write(1)
                print("[GPIO] Alarm stopped")

                return
        else:
            return  # 没有断电，直接返回

        current_time = utime.time()

        # 每1秒切换一次relay1状态
        if current_time - _alarm_state["last_flash_time"] >= 1:
            _alarm_state["last_flash_time"] = current_time
            _alarm_state["relay1_flash_state"] = not _alarm_state["relay1_flash_state"]

            # 控制relay1闪烁
            _relay1.write(1 if _alarm_state["relay1_flash_state"] else 0)

    except Exception as e:
        print("[GPIO] Power alarm update error: {}".format(e))


def get_alarm_status():
    """获取报警状态"""
    return {
        "power_failure": _alarm_state["power_failure"],
        "relay1_flashing": _alarm_state["power_failure"]
        and _alarm_state["relay1_flash_state"],
    }


def test_gpio():
    """测试GPIO功能"""
    print("[GPIO] Testing GPIO...")

    # 测试LED
    set_state_led_mode("on")
    utime.sleep(1)
    set_state_led_mode("off")

    set_net_led_mode("on")
    utime.sleep(1)
    set_net_led_mode("off")

    # 测试继电器
    set_relay(1, True)
    utime.sleep(1)
    set_relay(1, False)

    set_relay(2, True)
    utime.sleep(1)
    set_relay(2, False)

    # 测试数字输入
    di_status = read_digital_inputs()
    print("[GPIO] Digital inputs: {}".format(di_status))

    print("[GPIO] GPIO test completed")
